use std::collections::linked_list::LinkedList;
use bevy::prelude::*;
use bevy_inspector_egui::Inspectable;

pub struct ComponentsPlugin;

impl Plugin for ComponentsPlugin {
    fn build(&self, app: &mut App) {
        app.init_resource::<CursorPosition>()
            .add_system(update_cursor_position);
    }
}

#[derive(Component, Inspectable)]
pub struct Elevator {
    pub speed: f32,
    pub accelerate: f32,
    pub stop_at: i32,
}

#[derive(PartialEq, Copy, Clone)]
pub enum RequestType {
    FLOOR,
    UP,
    DOWN
}

pub struct ButtonRequest{
    pub req_type: RequestType,
    pub at: i32,
}

#[derive(Component)]
pub struct ReqQueue {
    pub request_queue: LinkedList<ButtonRequest>, // record the order of requested floor
}


// 当电梯到达制定楼层后，开门，往Elevator Entity中插入OpenTimer
#[derive(Component)]
pub struct OpenTimer {
    pub timer: Timer,
}

#[derive(Component)]
pub struct MainCamera;


/// Mouse location for building towers
#[derive(Debug, Clone, Default)]
pub struct CursorPosition(pub Vec2);

/// "Get mouse window position" example from the unofficial bevy cheat sheet docs (https://bevy-cheatbook.github.io/cookbook/cursor2world.html)
fn update_cursor_position(
    // need to get window dimensions
    windows: Res<Windows>,
    // query to get camera transform
    camera: Query<&Transform, With<MainCamera>>,
    mut cursor_position: ResMut<CursorPosition>,
) {
    // get the primary window
    let wnd = windows.get_primary().unwrap();

    // check if the cursor is in the primary window
    if let Some(pos) = wnd.cursor_position() {
        // get the size of the window
        let size = Vec2::new(wnd.width() as f32, wnd.height() as f32);

        // the default orthographic projection is in pixels from the center;
        // just undo the translation
        let p = pos - size / 2.0;

        // assuming there is exactly one main camera entity, so this is OK
        let camera_transform = match camera.get_single() {
            Ok(x) => x,
            Err(_) => return,
        };

        // apply the camera transform
        let pos_wld = camera_transform.compute_matrix() * p.extend(0.0).extend(1.0);
        cursor_position.0 = pos_wld.truncate().truncate();
    }
}

// todo: test
// fn resize_camera(
//     mut camera: Query<&mut Transform, With<MainCamera>>,
//     windows: Res<Windows>,
// ) {
//     if let Some(window) = windows.get_primary() {
//         for mut camera in camera.iter_mut() {
//             let scale = window.width().min(window.height()) / 1024.0;
//             camera.scale = Vec2::splat(1.0 / scale).extend(1.0);
//         }
//     }
// }

#[test]
fn test_linked_list_iter() {
    let mut list = LinkedList::new();
    list.push_back(1);
    list.push_back(2);
    list.push_back(3);
    let n = list.len();
    for i in 0..n {
        let ele = list.pop_front().unwrap();
        if ele != 2 {
            list.push_back(ele)
        }
    }
    println!("{:?}", list);
}